/**
* 作者: LuckKey
* 说明: 只支持32位的内联钩子
* 日期: 2025-03-14
* 版本: 1.0
*/

#pragma once
#include <Windows.h>
#include <iostream>

#pragma warning(push)
#pragma warning(disable: 4302)
#pragma warning(disable: 4311)

class InlineHook32 {
public:
	InlineHook32(void* pfSrc, void* pfDst, size_t code_len = 0) :m_pfSrc(pfSrc), m_pfDst(pfDst), m_code_len(code_len) {
		if (!m_pfSrc || !m_pfDst) {
			throw std::logic_error("InlineHook32 参数不能为空.");
		}
		
		if (code_len > 0) {
			if (code_len < 5) {
				throw std::logic_error("code_len 不能小于5.");
			}
		
			pOldFun = VirtualAlloc(NULL, m_code_len + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
			if (!pOldFun) {
				throw std::logic_error("VirtualAlloc 失败.");
			}
		}
	}

	~InlineHook32() {
		unhook();
		if (pOldFun) {
			VirtualFree(pOldFun, 0, MEM_RELEASE);
		}
	}

	void hook() {
		if (!m_isHook) {
			DWORD dwOldProtect = 0;
			VirtualProtect(m_pfSrc, m_code_len + 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);

			memcpy(m_oldData, m_pfSrc, 5);

			if (pOldFun) {
				memcpy(pOldFun, m_pfSrc, m_code_len);
				*(BYTE*)((DWORD)pOldFun + m_code_len) = 0xe9;
				*(DWORD*)((DWORD)pOldFun + m_code_len + 1) = (DWORD)m_pfSrc - (DWORD)pOldFun - 5;
			}

			BYTE* pFun = (BYTE*)m_pfSrc;
			pFun[0] = 0xe9;
			*(DWORD*)(pFun + 1) = (DWORD)m_pfDst - (DWORD)m_pfSrc - 5;

			VirtualProtect(m_pfSrc, 5, dwOldProtect, &dwOldProtect);
			m_isHook = true;
		}
	}

	void unhook() {
		if (m_isHook) {
			DWORD dwOldProtect = 0;
			VirtualProtect(m_pfSrc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
			memcpy(m_pfSrc, m_oldData, 5);
			VirtualProtect(m_pfSrc, 5, dwOldProtect, &dwOldProtect);
			m_isHook = false;
		}
	}

	void* getOldFun() {
		if (!pOldFun) {
			throw std::logic_error("OldFun 为指定字节码大小.");
		}
		return pOldFun;
	}

private:
	size_t m_code_len;
	BYTE m_oldData[5]{ };
	void* pOldFun{ };
	void* m_pfSrc;
	void* m_pfDst;
	bool m_isHook = false;	
};

#pragma warning(pop)

